#ifndef __I386_KERNEL_IO_H__
#define __I386_KERNEL_IO_H__

#include "common/basictypes.h"
#include "linux/compiler.h"

/* Basic port I/O */
static inline void outb(u8 v, u16 port) {
  asm volatile(
      "outb %0,%1"
      :
      : "a" (v), "dN" (port)
               );
}

static inline u8 inb(u16 port) {
  u8 v;
  asm volatile(
      "inb %1,%0"
      : "=a" (v)
      : "dN" (port)
               );
  return v;
}

static inline void outw(u16 v, u16 port) {
  asm volatile("outw %0,%1"
               :
               : "a" (v), "dN" (port)
               );
}

static inline u16 inw(u16 port) {
  u16 v;
  asm volatile(
      "inw %1,%0"
      : "=a" (v)
      : "dN" (port)
               );
  return v;
}

static inline void outl(u32 v, u16 port) {
  asm volatile(
      "outl %0,%1"
      :
      : "a" (v), "dN" (port)
               );
}

static inline u32 inl(u32 port) {
  u32 v;
  asm volatile(
      "inl %1,%0"
      : "=a" (v)
      : "dN" (port)
               );
  return v;
}

static inline void io_delay(void) {
  const u16 DELAY_PORT = 0x80;
  asm volatile(
      "outb %%al,%0"
      :
      : "dN" (DELAY_PORT)
               );
}

static inline void udelay(u32 ns) {
  for (int i = 0; i < ns; ++i) {
    io_delay();
  }
}

static inline unsigned char readb(const volatile void __iomem *addr)
{
  return *(volatile unsigned char __force *) addr;
}
static inline unsigned short readw(const volatile void __iomem *addr)
{
  return *(volatile unsigned short __force *) addr;
}
static inline unsigned int readl(const volatile void __iomem *addr)
{
  return *(volatile unsigned int __force *) addr;
}

static inline void writeb(unsigned char b, volatile void __iomem *addr) {
  *(volatile unsigned char __force*) addr = b;
}

static inline void writew(unsigned short b, volatile void __iomem *addr) {
  *(volatile unsigned short __force*) addr = b;
}

static inline void writed(unsigned int b, volatile void __iomem *addr) {
  *(volatile unsigned int __force*) addr = b;
}

#endif  // __I386_KERNEL_IO_H__

